﻿using System;
using System.Collections.Generic;
using System.Text;
using System.IO;

namespace Bencode
{
    class BencodeClass
    {
        // v0.14
        public static Object Decode(MemoryStream fileData)
        {
            // Convert MemoryStream to BinaryReader
            BinaryReader binaryReader = new BinaryReader(fileData, Encoding.Default);
            binaryReader.BaseStream.Position = 0;
            return DecodeObject(binaryReader); // Decode and return finalized object
        }

        private static Object DecodeObject(BinaryReader data)
        {
            char nextChar = data.ReadChar();
            if (nextChar == 'i') // Integer
            {
                String i = "";
                char c = (char)data.ReadByte();
                while (c != 'e')
                {
                    i = i + c;
                    c = (char)data.ReadByte();
                }
                return Convert.ToInt64(i);
            }
            else if (Char.IsDigit(nextChar)) // Byte[]
            {
                String len = "";
                while (nextChar != ':')
                {
                    len = len + nextChar;
                    nextChar = (char)data.ReadByte();
                }
                return data.ReadBytes(Convert.ToInt32(len));
            }
            else if (nextChar == 'd') // Dictionary
            {
                Dictionary<String, Object> dict = new Dictionary<String, Object>();
                // Iterate through each consecutive dictionary
                while (data.PeekChar() != 'e')
                {
                    // Get key
                    nextChar = (char)data.ReadByte();
                    String len = "";
                    while (nextChar != ':')
                    {
                        len = len + nextChar;
                        nextChar = (char)data.ReadByte();
                    }
                    // Add dictionary entry with key and recursive node as its value
                    String key = Encoding.UTF8.GetString(data.ReadBytes(Convert.ToInt16(len)));
                    dict.Add(key, DecodeObject(data));
                }
                data.ReadChar(); // discard e
                return dict;
            }
            else if (nextChar == 'l') // List
            {
                List<Object> list = new List<Object>();
                // Iterate through each consecutive item
                char peek = (char)data.PeekChar();
                while (peek != 'e')
                {
                    list.Add(DecodeObject(data));
                    peek = (char)data.PeekChar();
                }
                data.ReadChar(); // discard e
                return list;
            }
            else
            {
                return null; // Parsing error
            }
        }
    }
}
